/*Copyright 2010 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.*/

//////BEGIN INTRODUCER API//////////
/*
window.introducer =
interface Introducer {
  void register(in Node anchor, in Registration registration, in Function callback);
  boolean transfer(in Registration registration, in DOMString origin);
  DOMString[] getRegisteredIds();
  void request(in Node anchor, in [media-range] types, in Function callback);
  DOMString[] getSupportedTypes(in DOMString[] wanted);
  receiveCustomerMessages(in DOMString[] registrationOrigin, in function eventHandler);
};
*/

function initIntroducer(introducerFrame) {

    var introducer = {};
    var INTRODUCER_ORIGIN = "http://webintroducer.googlecode.com";
    var INTRODUCER_PATH = INTRODUCER_ORIGIN + "/hg/";
    //window.introducer._initialized = false;
    //window.introducer._localHandler = '/introducer-local-handler.html';
    //window.introducer._globalHandler = '/introducer-global.html';

    //window.introducer._init = function() {
    //  window.introducer._localFrame = document.createElement("iframe");
    //  
    //}
    // 
    if (typeof introducerFrame === "undefined") {
        introducerFrame = document.getElementById("introducer-frame").contentWindow;
    }
    var requestConsentFrameURI = INTRODUCER_PATH + "introducer-menu.html?";
    var forwardFrameURI =  INTRODUCER_PATH + "introducer-forward.html?";
    var rpcclient = jsonrpc_client(getPostMessageSender(introducerFrame, '*'));
    rpcclient.addMessageReceiver(getPostMessageReceiver("*", introducerFrame));
    var rpcclient_parent;
    var providerRequests = [];
    var emulatedMessageChannels = []; // emulated message "channels" (port, emulateMessage)
    var impl = {};
    
    impl.getElementId = function(element) {
        return null;
    };
    
    var supportedTypes = null;
    var currentOriginIds = null;
    
    /*
    var updateData = function() {
        rpcclient.call("getRegisteredIds", [], function(data) {
            currentOriginIds = data;
        });
        rpcclient.call("getSupportedTypes", [], function(data) {
            supportedTypes = data;
        });
    };*/
    
    //updateData();
    
    var getDOMPosition = function(el) {
        return null;
    };
    
    var mediaRangeIntersects = function(aRange, bRange) {
        return true;
    };
    
    var getOrigin = function(location) {
      return l.protocol + "//" + location.host + (location.port && ":" + location.port);
    };

    var createEmulatedMessageChannel = function(sendFunction) {
        var mp = document.createElement("EmulatedMessagePort");
        mp.postMessage = function(message) {
            sendFunction(message);
        };
        return {
            port: mp,
            emulateMessage: function(message) {
                //TODO: IE Compatibility (does not support createEvent, see createEventObject)
                var e = document.createEvent("MessageEvent");
                e.initMessageEvent("message", false, false, message);
                mp.dispatchEvent(e);
            }
        };
    };

    introducer.origin = INTRODUCER_ORIGIN;
    
    introducer.register = function(sender, registration, callback) {
        rpcclient.call("register", [impl.getElementId(sender), registration], callback, function(error) { console.debug(error); if (callback) { callback(null); } });
    };

    introducer.transfer = function(registrationId, neworigin, callback) {
        rpcclient.call("transfer", [registrationId, neworigin], callback, function(error) { console.debug(error); if (callback) { callback(null); } });
    };

    introducer.request = function(sender, types, callback) {
        if (!sender || typeof sender === "undefined") { throw "TypeError: sender not provided"; }
        if (typeof callback !== "function") { throw "TypeError: callback not a valid function"; }
        
        var requestSuccessHandler = function(response) {
            var providerInstance = {};
            
        };
        rpcclient.subscribe("request", [impl.getElementId(sender), types], 
            function(requestNotice) {
                var ifrm;
                var win;
                if (requestNotice === null) {
                    callback(null);
                    return;
                }
                if (requestNotice.type === "showMenu") {
                    providerRequests[requestNotice.requestId] = {};
                    ifrm = document.createElement("iframe");
                    ifrm.src = requestConsentFrameURI + requestNotice.requestId;
                    sender.appendChild(ifrm);
                    providerRequests[requestNotice.requestId].menuFrame = ifrm;
                } else if (requestNotice.type === "showProvider") {
                    providerRequests[requestNotice.requestId].menuFrame.parentElement.removeChild(providerRequests[requestNotice.requestId].menuFrame);
                    delete providerRequests[requestNotice.requestId].menuFrame;
                    if (requestNotice.popup) {
                        providerRequests[requestNotice.requestId].providerWindow = window.open(null, "" + requestNotice.requestId);
                    } else {
                    //possibly reuse iframe (any risks?)
                        ifrm = document.createElement("iframe");
                        ifrm.src = forwardFrameURI + requestNotice.requestId;
                        sender.appendChild(ifrm);
                        providerRequests[requestNotice.requestId].providerFrame = ifrm;
                        providerRequests[requestNotice.requestId].providerWindow = ifrm.contentWindow;
                    }
                } else if (requestNotice.type == "providerReady") {
                    ifrm = providerRequests[requestNotice.requestId].providerFrame;
                    win = providerRequests[requestNotice.requestId].providerWindow;
                    
                    emulatedMessageChannels[requestNotice.requestId] = createEmulatedMessageChannel(function(message) {
                        rpcclient.call("sendMessage", [requestNotice.requestId, message, false], function() {}, function(error) {console.debug(error); });
                    });
                    
                    /*var safePostMessage = function(message, targetOrigin) { //NOTE: Should messages be limited to strings, or is anything JSONable ok
                        if (typeof targetOrigin === "string") {
                            return win.postMessage(message, targetOrigin);
                        } else {
                            if (typeof targetOrigin === "object" && typeof targetOrigin.requestId !== "undefined") {
                                if (typeof providerRequests[targetOrigin.requestId] !== "undefined") {
                                    rpcclient.call("sendMessage", [targetOrigin.requestId, message, false], function() {}, function(error) {console.debug(error); });
                                }
                                return;
                            }
                            return win.postMessage(message, targetOrigin);
                        }
                    };*/
                    
                    rpcclient.subscribe("receiveProviderMessages", [requestNotice.requestId],
                        function(remoteMessage) {
                            if (remoteMessage !== true) {
                                emulatedMessageChannels[requestNotice.requestId].emulateMessage(remoteMessage.data);
                            }
                        },
                        function(error) {});
                        
                    callback({
                        iframe: ifrm,
                        window: win,
                        messagePort: emulatedMessageChannels[requestNotice.requestId].port
                    });
                }
            }, 
            function(error) { 
                console.debug(error);
                if (callback) {
                    callback(null);
                }
            });
    };
/* // now unsupported
    introducer.getSupportedTypes = function(wanted) {
        //TODO: filtering
        return supportedTypes;
    };

    introducer.getRegisteredIds = function() {
        return currentOriginIds;
    };
*/
    //For Use on Provider Page (can this method be made available/unavailable accordingly?)
    introducer.receiveCustomerMessages = function(registrationOriginList, supportedTypes, callback) {
        var requestId;
        if (typeof callback !== "function") { throw "TypeError: callback not a valid function"; }
        try {
            requestId = parseInt(window.name, 10);
        } catch (error) {
            throw "Error: receiveCustomerMessages must be called from within a Provider instance.";
        }
        
        
        var cwins;
        try {
            if (window.opener !== null) {
                cwins = window.opener.frames;
            } else {
                cwins = window.parent.frames;
            }
        } catch(e) {
            return;
        }
        
        // Attempts to locate the introducer by the parent page
        var tempclient;
        for (var i = 0; i < cwins.length; i++) {
            if (cwins[i] !== window && cwins[i] !== window.parent) {
                try {
                    tempclient = jsonrpc_client(getPostMessageSender(cwins[i], INTRODUCER_ORIGIN), "temp" + i); // fill in
                    tempclient.addMessageReceiver(getPostMessageReceiver(INTRODUCER_ORIGIN, cwins[i]));
                    tempclient.subscribe("receiveCustomerMessages", [requestId, registrationOriginList, supportedTypes], (function(r) {
                        return function(remoteMessage) {
                            if (typeof rpcclient_parent === "undefined") {
                                rpcclient_parent = r;
                            } else if (rpcclient_parent !== r) {
                                return; // first parent found is the only parent allowed
                            }
                            if (remoteMessage === true) {
                                emulatedMessageChannels[requestId] = createEmulatedMessageChannel(function(message) {
                                    rpcclient_parent.call("sendMessage", [requestId, message, false], function() {}, function(error) { console.debug(error); });
                                });
                                callback(emulatedMessageChannels[requestId].port);
                            } else {
                                emulatedMessageChannels[requestId].emulateMessage(remoteMessage.data);
                            }
                            //Pre MessageChannels:
                            /*var messageEvent = document.createEvent("Event");
                            messageEvent.initEvent("message", true, true);
                            if (window.parent) {
                                messageEvent.source = window.parent; // for iframe case
                            } else {
                                messageEvent.source = window.opener; // for new window case
                            }
                            messageEvent.origin = remoteMessage.origin;
                            messageEvent.data = remoteMessage.data;
                            window.dispatchEvent(messageEvent);
                                        //eventHandler();
                                    };
                                }(tempclient)), function(error) { console.debug(error); });
                            } catch(e) {}*/
                        };
                    }(tempclient)));
                } catch(e2) {
                    // do nothing
                }
            }
        }
    };
    
    
    window.introducer = introducer;
    window.rc = rpcclient;
}